package com.longteng.diamond.service;

import com.longteng.diamond.constant.BuildTestStatus;
import com.longteng.diamond.dao.InterfaceTestMapper;
import com.longteng.diamond.dao.TestCaseMapper;
import com.longteng.diamond.domain.*;
import com.longteng.diamond.factory.ClientFactory;
import com.longteng.diamond.po.RequestResult;
import com.longteng.diamond.process.ClientProcesstor;
import com.longteng.diamond.util.AssertResult;
import com.longteng.diamond.util.DateUtil;
import com.longteng.diamond.util.ReportLogFileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator
 * DATE : 2018/7/14
 * TIME : 17:41
 * PROJECT : java-lesson
 * PACKAGE : com.longteng.lesson
 *
 * @author <a href="mailto:taki@qq.com">Administrator</a>
 */
@Component
@Slf4j
public class RunTestService {
    @Autowired
    TestCaseMapper testCaseMapper;
    @Autowired
    BuildTestService buildTestService;
    @Autowired
    InterfaceTestMapper interfaceTestMapper;
    @Autowired
    TestPlanService testPlanService;
    @Autowired
    ClientFactory clientFactory;
    @Autowired
    AssertResult assertResult;
    @Value("${report.shareDir}")
    private String shareDir;
    private ReportLogFileUtil logFileUtil = null;

    /**
     * 运行测试
     *
     * @param runTestContext
     * @return
     */
    public void runTestByBuildTest(RunTestContext runTestContext) {
        Integer buildTestId = runTestContext.getBuildTestId();
        logFileUtil = new ReportLogFileUtil(shareDir + File.separator + buildTestId + ".log");
        runTestContext.setReportLogFileUtil(logFileUtil);
        logFileUtil.write("开始初始化运行数据!");
        BuildTest buildTest = buildTestService.buildRunTest(buildTestId);
        runTestContext.setBuildTest(buildTest);
        runTestContext.initBuildTest();
        List<BuildTestInterface> buildTestInterfaceList = buildTest.getBuildTestInterfaceList();
        int interfaceSize = buildTestInterfaceList.size();
        logFileUtil.write("初始化接口信息完成,运行接口数量:" + interfaceSize);
        /**记录这次执行的开始时间**/
        runTestContext.setBuildStartTime(System.currentTimeMillis());
        buildTest.setStartTime(DateUtil.getCurrentTime());
        try {
            for (BuildTestInterface buildTestInterface : buildTestInterfaceList) {
                String interfaceType = buildTestInterface.getInterfaceType();
                String interfaceAliasName = buildTestInterface.getInterfaceAliasName();
                runTestContext.setBuildTestInterface(buildTestInterface);
                runTestContext.initInterfaceStatusSize();
                logFileUtil.writeSpan("初始化测试接口名称:[" + interfaceAliasName + "]完成,接口类型:[" + interfaceType + "]");
                /**获取执行引擎:http、dubbo**/
                ClientProcesstor client = clientFactory.getClient(interfaceType);
                List<BuildTestCase> buildTestCaseList = buildTestInterface.getBuildTestCaseList();
                runTestContext.setTestCaseList(buildTestCaseList);
                /**记录接口运行开始时间**/
                Long interfaceStartTime = System.currentTimeMillis();
                runTestContext.setStartTime(interfaceStartTime);
                /**开始执行当前接口下的所有用例**/
                this.runTestCase(runTestContext, client);
                /**记录接口运行结束时间**/
                Long interfaceEndTime = System.currentTimeMillis();
                runTestContext.setEndTime(interfaceEndTime);
                logFileUtil.write("接口[" + interfaceAliasName + "]运行完成,运行时长:" + (interfaceEndTime - interfaceStartTime) / 1000);
                /**计算用例数量、通过率、执行时间**/
                runTestContext.interfaceCalculation();
                /**如果当前接口下面没有测试用例状态全部设置成0**/
                if (CollectionUtils.isEmpty(runTestContext.getTestCaseList())) {
                    runTestContext.getBuildTestInterface().setStatus(BuildTestStatus.noCase);
                    runTestContext.getBuildTestInterface().setPassRate("0%");
                    buildTestService.updateBuildInterface(runTestContext.getBuildTestInterface());
                    continue;
                }else {
                    /**更新当前接口的执行状态以及执行用例情况**/
                    buildTestService.updateBuildInterface(runTestContext.getBuildTestInterface());
                }
                /**更新当前接口所有用例的执行状态以及执行用例情况**/
                buildTestService.updateBuildTestCases(runTestContext.getTestCaseList());
                /**更新整个运行集合的状态,每两个接口更新1次build**/
                if (interfaceSize % 2 == 0) {
                    buildTestService.updateBuildTest(runTestContext.getBuildTest());
                }
            }
        } catch (Exception e) {
            log.error("执行测试出现异常",e);
            logFileUtil.writeRedSpan(e.toString());
        }finally {
            /**目前可能出现未知错误不管什么情况先更新buildTest**/
            buildTestService.updateBuildTest(runTestContext.getBuildTest());
        }

    }

    /**
     * 运行测试用例
     *
     * @param runTestContext
     * @return
     */
    private void runTestCase(RunTestContext runTestContext, ClientProcesstor client) {
        List<BuildTestCase> buildTestCaseList = runTestContext.getTestCaseList();
        runTestContext.setInterfaceAllSize(buildTestCaseList.size());
        logFileUtil.write("初始化测试用例");
        for (BuildTestCase buildTestCase : buildTestCaseList) {
            logFileUtil.write("执行用例名称:[" + buildTestCase.getTestCaseName() + "]");
            runTestContext.setBuildTestCase(buildTestCase);
            try {
                client.runTest(runTestContext);
            }catch (Exception e){
                log.error("client执行异常,client名字{}",client.getClass().getName(),e);
                logFileUtil.writeRedSpan(e.toString());
            }
            assertResult.assertResult(runTestContext);
        }
    }


    /**
     * 单个用例调用
     *
     * @param testCase
     * @return requestResult
     */
    public RequestResult runTest(TestCase testCase) {
        RequestResult requestResult = new RequestResult();
        InterfaceTest interfaceTest = interfaceTestMapper.findInterfaceTestById(testCase.getInterfaceId());
        if (null == interfaceTest) {
            requestResult.setSuccess(false);
            requestResult.setMsg("接口:[" + testCase.getInterfaceId() + " ]不存在,请确认是否删除");
            return requestResult;
        }
        ClientProcesstor processtor = clientFactory.getClient(interfaceTest.getInterfaceType());
        processtor.runTest(interfaceTest, testCase, requestResult);
        return requestResult;
    }
}
